#ifndef XLCOMM_NET_RPCCHANNELCLIENT_H_
#define XLCOMM_NET_RPCCHANNELCLIENT_H_

#include <google/protobuf/service.h>

#include "xlcomm/define.h"
#include "xlcomm/net/protorpc/rpc.pb.h"
#include "xlcomm/net/protorpc/rpc_message_codec.h"
#include "xlcomm/net/tcp_client.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {
namespace net {

class XLCOMM_API RpcChannelClient : public google::protobuf::RpcChannel,
                                    noncopyable {
 public:
  RpcChannelClient(net::EventLoop* loop, const net::InetAddress& server_addr);

  void Connect() { client_.Connect(); }
  void Disconnect() { client_.Disconnect(); }

  void CallMethod(const google::protobuf::MethodDescriptor* method,
                  google::protobuf::RpcController* controller,
                  const google::protobuf::Message* request,
                  google::protobuf::Message* response,
                  google::protobuf::Closure* done) override;

 private:
  struct OutstandingCall {
    google::protobuf::Message* response;
    google::protobuf::Closure* done;
  };
  using Outstandings = std::map<uint64_t, OutstandingCall>;

  void OnRpcMessage(const net::TcpConnectionPtr& conn,
                    const RpcMessage& rpcmsg);

  net::EventLoop* loop_;
  net::TcpClient client_;
  Outstandings outstandings_;
  RpcMessageCodec codec_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_RPCCHANNELCLIENT_H_